package swimv2gm.bl.session;

import java.util.List;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.jboss.ejb3.annotation.RemoteBinding;

import swimv2gm.bl.domain.Friendship;
import swimv2gm.bl.domain.FriendshipPK;
import swimv2gm.bl.domain.User;
import swimv2gm.bl.util.UserData;

@Stateless
@RemoteBinding(jndiBinding = "FriendshipManager")
public class FriendshipManagerBean implements FriendshipManager {
	@PersistenceContext(unitName = "swimv2")
	private EntityManager manager;

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean addRequest(long mitt,long dest) {
		if (mitt == dest || findFriendship(mitt,dest) != null || findFriendship(dest,mitt) != null) {
			return false;
		}
		else {
			User mitt_u = manager.getReference(User.class,mitt);
			User dest_u = manager.getReference(User.class,dest);

			if (mitt_u == null || dest_u == null) {
				return false;
			}
			Friendship f = new Friendship();
			f.setAccettata(false);
			f.setMittente(mitt_u);
			f.setDestinatario(dest_u);
			mitt_u.addSentFriendshipRequest(f);
			dest_u.addReceivedFriendshipRequest(f);
			manager.persist(f);
			return true;
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Friendship findFriendship(long mitt,long dest) {
		FriendshipPK fk = new FriendshipPK();
		fk.setMittente(manager.getReference(User.class,mitt));
		fk.setDestinatario(manager.getReference(User.class,dest));
		return manager.find(Friendship.class,fk);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public List<UserData> friendsWithAbility(long uid,long cid) {
		User u = manager.find(User.class,uid);

		Query q = manager
				.createQuery("select new swimv2gm.bl.util.UserData(u.uid,u.nome,u.cognome) from amicizie f, competenze c, in (c.utenti) u where c.cid=:cid and f.accettata=true and f.mittente=:uid and u = f.destinatario order by u.cognome");

		q.setParameter("uid",u);
		q.setParameter("cid",cid);

		List<UserData> users = q.getResultList();

		q = manager
				.createQuery("select new swimv2gm.bl.util.UserData(u.uid,u.nome,u.cognome) from amicizie f, competenze c, in (c.utenti) u where c.cid=:cid and f.accettata=true and f.destinatario=:uid and u = f.mittente order by u.cognome");

		q.setParameter("uid",u);
		q.setParameter("cid",cid);

		users.addAll(q.getResultList());

		return users;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public List<User> getFriends(long uid) {
		Query q = manager
				.createQuery("select a.destinatario from amicizie a where a.mittente.uid=:myid and a.accettata = true");
		q.setParameter("myid",uid);
		List<User> friends = q.getResultList();
		q = manager
				.createQuery("select a.mittente from amicizie a where a.destinatario.uid=:myid and a.accettata = true");
		q.setParameter("myid",uid);
		List<User> r = q.getResultList();
		friends.addAll(r);
		return friends;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public List<UserData> getFriendsData(long uid) {
		List<UserData> friends = getUserData(uid,true,true);
		friends.addAll(getUserData(uid,false,true));

		return friends;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public List<User> getPendingFriends(long uid,boolean received) {
		String query = received ? "select a.mittente from amicizie a where a.destinatario.uid=:myid and a.accettata = false"
				: "select a.destinatario from amicizie a where a.mittente.uid=:myid and a.accettata = false";
		Query q = manager.createQuery(query);
		q.setParameter("myid",uid);

		List<User> requests = q.getResultList();

		return requests;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public List<UserData> getPendingFriendsData(long uid,boolean received) {
		return getUserData(uid,received,false);
	}

	/**
	 * {@inheritDoc}
	 */
	private List<UserData> getUserData(long uid,boolean received,boolean accepted) {
		String query = "select new swimv2gm.bl.util.UserData(u.uid,u.nome,u.cognome) from amicizie f, in (f."
				+ (received ? "mittente" : "destinatario") + ") u where f." + (received ? "destinatario" : "mittente")
				+ "=:uid and f.accettata = :accepted";
		Query q = manager.createQuery(query);
		q.setParameter("uid",manager.find(User.class,uid));
		q.setParameter("accepted",accepted);

		return q.getResultList();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean processRequest(long mitt,long dest,boolean accepted) {
		Friendship f = findFriendship(mitt,dest);
		if (f == null)
			return false;
		else {
			if (accepted) {
				f.setAccettata(true);
			}
			else {
				manager.remove(f);
			}
			manager.flush();
			return true;
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean removeFriendship(long u1,long u2) {
		Friendship f = findFriendship(u1,u2);
		if (f == null)
			f = findFriendship(u2,u1);
		if (f == null)
			return false;

		manager.remove(f);
		manager.flush();
		return true;
	}
}
